package com.example.demo.controller;


import org.apache.commons.io.FileUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.UUID;

@Controller
public class OperationUploadDownloadController {


    @GetMapping("/upload")
    public String upload() {
        return "upload";
    }


    //文件上传页面的from表单提交的地址，与这里保持一致否则提交的东西拿不到
    @PostMapping("/uploadFile")

    //将上传的文件以数组的形式拿到
    //上传的文本框的名字 要与这里定义的参数名字保持一致 否则也拿不到上传的数据（fileUpload）
    public String uploadFile(MultipartFile[] fileUpload, Model model) {
        model.addAttribute("uploadStatus", "上传成功");
        //将需要上传的数据以数组的形式进行获取 并且在其中进行操作
        for (MultipartFile file :
                fileUpload) {
            //getOriginalFilename() 作用：获取文件的全路径名（例如：E:\备份\【课表】软件3月份课表-胡昆.xlsx）
            String filename = file.getOriginalFilename();
            //lastIndexOf("\\") 作用：拿到需要的部分（非全路径名） 最后一个“/”后的内容（包括“/”）
            //返回值是一个索引
            int index = filename.lastIndexOf("\\");//转义字符
            //substring(index + 1) 作用：拿到需要的部分 拿到以该索引开头到末尾的部分
            filename = filename.substring(index + 1);
            //防止上传文件的过程中发生重名 根据系统自动生成随机数进行定义新的名字
            //UUID.randomUUID() 作用：系统自动生成随机数  再加上文件原来需要的路径 组成新的名字
            filename = UUID.randomUUID() + "_" + filename;
            //定义一个新的文件(全路径名的方式进行定义)
            String dirPath = "F:/file/";
            //new File(dirPath) 作用：生成一个文件 根据文件的全路径名进行生成
            File filePath = new File(dirPath);
            //判断是否存在该文件
            if (!filePath.exists()) {
                //如果不存在 创建出该文件
                filePath.mkdirs();
            }
            try {
                //transferTo(new File(dirPath + filename)) 作用：将数据传输到指定的文件下
                //生成一个文件（本身没有）对象 将数据放入到该文件（对象）中
                file.transferTo(new File(dirPath + filename));
            } catch (IOException e) {
                e.printStackTrace();
                model.addAttribute("uploadStatus", "上传失败");
            }
        }

        return "upload";
    }

    @GetMapping("/toDownload")
    public String toDownload() {
        return "download";
    }


    //根据前面超链的跳转地址（服务） 到这里并拿到跳转时候的参数（filename）
    @GetMapping("/download")
    public ResponseEntity<byte[]> fileDownload(HttpServletRequest request, String filename) throws Exception {
        //定义一个全路径的地址
        String dirPath = "F:/wenjian/";

//        File file = new File(dirPath + filename);
        //生成一个文件对象（需要下载的文件本身就存在在服务器中（本机就是服务器） 只是生成一个对象方便操作）
        //根据全路径名 + 文件名进行生成一个对象
        File file = new File(dirPath + File.separator + filename);
        //生成一个关于浏览器的头对象 作用：方便调用其中的方法
        HttpHeaders httpHeaders = new HttpHeaders();


        //getFilename(request, filename) 作用：将中文文件名改成英文的
        //原因：很多浏览器中不识别中文 所以只能使用英文
        //切记：他的作用只是为了能使得浏览器进行识别名字而已 防止下载后的文件的名字为空
        //真正需要下载的文件不需要进行此操作（中文转英文）
        //原因：是根据文件进行下载（全路径文件）
        //不用此操纵也可以下载成功 只是下载后的文件名是空的
        filename = getFilename(request, filename);


        //setContentDispositionFormData("attachment", filename) 作用：激活文件下载的对话框
        //filename 下载的文件名以及格式类型
        httpHeaders.setContentDispositionFormData("attachment", filename);
        //表明下载文件的格式类型
        //APPLICATION_OCTET_STREAM：二进制流数据（如常见的文件下载）
        httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        try {
            //在浏览器中返回一个对象 ResponseEntity（FileUtils.readFileToByteArray(file) 作用：把你需要下载的文件 以字节数的形式读出来）
            // 这样你下载的文件 已经到了浏览器的内存中了 接下来 弹出另存为的对话框
            //HttpStatus.OK ==200表示下载成功
            return new ResponseEntity<>(FileUtils.readFileToByteArray(file), httpHeaders, HttpStatus.OK);
        } catch (IOException e) {
            e.printStackTrace();
            //在浏览器中返回一个对象 ResponseEntity（e.getMessage() 失败的信息提示 .getBytes()）
            //HttpStatus.EXPECTATION_FAILED 表示文件下载失败
            return new ResponseEntity<>(e.getMessage().getBytes(), HttpStatus.EXPECTATION_FAILED);
        }

    }


    //将中文文件名改成英文的方法
    private String getFilename(HttpServletRequest request, String filename)
            throws Exception {
        String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};
        String userAgent = request.getHeader("User-Agent");
        for (String keyWord : IEBrowserKeyWords) {
            if (userAgent.contains(keyWord)) {
                return URLEncoder.encode(filename, "UTF-8").replace("+", " ");
            }
        }
        return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
    }
}
